"""
改造rest_framework模块
"""
import json
from djangomodel.log import output_log
from django.utils.decorators import classonlymethod
from rest_framework.generics import GenericAPIView
from rest_framework.serializers import ModelSerializer,Serializer
from django.http import JsonResponse
from django.db.models import CharField
from djangomodel.err import MethodNotAllowedErr, PermissionDeniedErr
from org.models import UserModel,RoleModel
from .permission import role_level

## 通用restful接口
class MyView:

    http_method_names = [
        "get",
        "post",
        "put",
        "patch",
        "delete",
        "head",
        "options",
        "trace",
    ]

    def __init__(self, **kwargs):
        for key, value in kwargs.items():
            setattr(self, key, value)

    @classonlymethod
    def as_view(cls ,**initkwargs):
        def view(request, *args, **kwargs):
            self = cls(**initkwargs)
            self.setup(request, *args, **kwargs)
            if not hasattr(self, "request"):
                raise AttributeError(
                    "%s instance has no 'request' attribute. Did you override "
                    "setup() and forget to call super()?" % cls.__name__
                )
            return self.dispatch(request, *args, **kwargs)
        return view

    def setup(self, request, *args, **kwargs):
        if hasattr(self, "get") and not hasattr(self, "head"):
            self.head = self.get
        self.request = request
        self.args = args
        self.kwargs = kwargs

    def dispatch(self, request, *args, **kwargs):
        if request.method.lower() in self.http_method_names:
            handler = getattr(
                self, request.method.lower(), self.http_method_not_allowed
            )
        else:
            handler = self.http_method_not_allowed
        return handler(request, *args, **kwargs)

    def http_method_not_allowed(self, request, *args, **kwargs):
        raise MethodNotAllowedErr(f"请求方法不允许,method:{request.method}")

class MyGenericAPIView(GenericAPIView):
    """
        请配置 models = None #模型
              exclude = () #排除字段
        重写 http_method_names 限定方法
        重写 mothod_level 改变接口权限
        重写 custom_permissions方法 自定义权限检查
    """
    queryset = None  # 数据集
    serializer_class = None  # 序列化器
    models = None  # 模型
    exclude = ()  # 排除字段
    http_method_names = [
        "get",
        "post",
        "put",
        "patch",
        "delete",
        "head",
        "options",
        "trace",
    ]  # 允许METHOD接口
    method_level = {
        "get":0,
        "post":0,
        "put":0,
        "delete":0,
    }  # 接口权限等级

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        # 获取数据集
        if self.queryset is None:
            self.queryset = self.models.objects.all()
        # 序列化器自定义 或者 自动根据模型及排除字段生成
        if self.serializer_class is not None:
            pass
        else:
            self.serializer_class = self.make_serializer_class()

    # 根据模型创建序列化器
    def make_serializer_class(self):
        if self.exclude != []:
            class MySerializer(ModelSerializer):
                class Meta:
                    model = self.models
                    exclude = self.exclude

            return MySerializer
        else:
            class MySerializer(ModelSerializer):
                class Meta:
                    model = self.models
                    fields = '__all__'
            return MySerializer

    # 重写方法
    def http_method_not_allowed(self, request, *args, **kwargs):
        raise MethodNotAllowedErr(f"请求方法不允许! {request.path}:{request.method}")

    # 权限相关方法
    def initial(self, request, *args, **kwargs):
        """
        Runs anything that needs to occur prior to calling the method handler.
        """
        self.format_kwarg = self.get_format_suffix(**kwargs)

        # Perform content negotiation and store the accepted info on the request
        neg = self.perform_content_negotiation(request)
        request.accepted_renderer, request.accepted_media_type = neg

        # Determine the API version, if versioning is in use.
        version, scheme = self.determine_version(request, *args, **kwargs)
        request.version, request.versioning_scheme = version, scheme

        # Ensure that the incoming request is permitted
        self.check_permissions(request)

        if hasattr(self,"custom_permissions"):
            self.custom_permissions(request)

    # 通用权限检查
    def check_permissions(self,request):
        userid = request._request.userid
        roles = UserModel.objects.get(pk=userid).roles.all()
        user_level = 0
        for role in roles:
            rolelevel = role_level.get(role.name)
            if user_level < rolelevel:
                user_level = rolelevel
        method = request.method.lower()
        interface_level = self.method_level.get(method)
        if interface_level > user_level:
            # 接口等级比用户等级高
            raise PermissionDeniedErr()

    # 自定义权限检查
    def custom_permissions(self,request):
        pass

    # get方法，获取全部或部分数据
    def get(self, request):
        uuid = self.request.query_params.get('uuid', None)
        id = self.request.query_params.get('id', None)
        if uuid is None and id is None:
            serializer = self.serializer_class(instance=self.get_queryset(), many=True)
            return JsonResponse({"status": 200, "data": serializer.data})
        elif uuid is None and id is not None:
            data = self.get_queryset().filter(id=id)
            if data.exists():
                serializer = self.serializer_class(instance=data[0])
                return JsonResponse({"status": 200, "data": serializer.data})
            else:
                return JsonResponse({"status": 200, "data": {}})
        elif id is None and uuid is not None:
            data = self.get_queryset().filter(uuid=uuid)
            if data.exists():
                serializer = self.serializer_class(instance=data)
                return JsonResponse({"status": 200, "data": serializer.data})
            else:
                return JsonResponse({"status": 200, "data": {}})

    # post方法，新增数据
    def post(self, request):
        serializer = self.serializer_class(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return JsonResponse({"status": 200, "msg": "创建成功！"})
        else:
            return JsonResponse({"status": 400, "msg": "创建失败！", "err": serializer.errors})

    # 更新方法
    def put(self, request):
        uuid = self.request.query_params.get('uuid', None)
        id = self.request.query_params.get('id', None)
        if uuid is not None and id is None:
            model_obj = self.get_queryset().filter(uuid=uuid)
            if model_obj.exists():
                serializer = self.serializer_class(instance=model_obj[0], data=request.data, partial=True)
            else:
                return JsonResponse({"status": 400, "msg": "您所更新的资源不存在！"})
        elif uuid is None and id is not None:
            model_obj = self.get_queryset().filter(id=id)
            if model_obj.exists():
                serializer = self.serializer_class(instance=model_obj[0], data=request.data, partial=True)
            else:
                return JsonResponse({"status": 400, "msg": "您所更新的资源不存在！"})
        if serializer.is_valid():
            serializer.save()
            return JsonResponse({"status": 200, "msg": "更新成功！"})
        else:
            return JsonResponse({"status": 400, "msg": "更新失败！", "err": serializer.errors})

    # 删除方法
    def delete(self, request):
        uuid = self.request.query_params.get('uuid', None)
        id = self.request.query_params.get('id', None)
        if uuid is not None and id is None:
            model_obj = self.get_queryset().filter(uuid=uuid)
            if model_obj.exists():
                model_obj[0].delete()
            else:
                return JsonResponse({"status": 200, "msg": "该资源已删除！"})
        elif uuid is None and id is not None:
            model_obj = self.get_queryset().filter(id=id)
            if model_obj.exists():
                model_obj[0].delete()
            else:
                return JsonResponse({"status": 200, "msg": "该资源已删除！"})
        return JsonResponse({"status": 200 ,"msg": "删除成功！"})


